import { Image, View, Video } from '@tarojs/components';
import Taro from '@tarojs/taro';
import classnames from 'classnames';
import { useEffect, useMemo, useState } from 'react';

import { PREFIX_CLS } from './constants';
import { isVideo } from './utils';

import type { ImageProps, ITouchEvent, VideoProps } from '@tarojs/components';
import type { CSSProperties, FC } from 'react';

import { Icon } from '@/components';
import { getSuffixFromUrl } from '@/utils';

import './index.scss';

type Source = Taro.previewMedia.Sources;

// 公共属性
interface CommonProps {
  type?: 'image' | 'video';
  className?: string;
  style?: CSSProperties;
  width?: number | string;
  height?: number | string;
  src?: string;
  preview?: boolean;
  onClick?: (e: ITouchEvent) => void;
  lazyLoad?: boolean; // 是否懒加载
  placeholder?: string; // 占位图
  showLoading?: boolean; // 是否显示加载状态
  videoPoster?: string; // 视频封面图（某一帧）
  autoGeneratePoster?: boolean; // 是否自动生成视频封面
}

// Image 专属属性
type ImageExtraProps = {
  mode?: ImageProps['mode'];
  showMenuByLongpress?: ImageProps['showMenuByLongpress'];
};

// Video 专属属性（常用视频属性透传）
type VideoExtraProps = Partial<
  Pick<
    VideoProps,
    | 'controls'
    | 'autoplay'
    | 'loop'
    | 'muted'
    | 'poster'
    | 'showCenterPlayBtn'
    | 'showProgress'
    | 'showPlayBtn'
    | 'showFullscreenBtn'
    | 'showMuteBtn'
    | 'objectFit'
  >
>;

// 组合类型：根据 type 区分，同时保留未显式声明 type 的兼容用法
type ImagePropsCombined = CommonProps & { type: 'image' } & ImageExtraProps;
type VideoPropsCombined = CommonProps & { type: 'video' } & VideoExtraProps;
type CompatibleProps = CommonProps & { type?: undefined } & ImageExtraProps &
  VideoExtraProps;

export type MediaProps =
  | ImagePropsCombined
  | VideoPropsCombined
  | CompatibleProps;

const Media: FC<MediaProps> = (props) => {
  const {
    className,
    style,
    width,
    height,
    src,
    preview = false,
    onClick,
    lazyLoad = true, // 默认开启懒加载
    placeholder,
    showLoading = true,
    videoPoster,
    autoGeneratePoster = false, // 默认关闭自动生成，避免 URL 不支持导致加载失败
  } = props;

  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(false);

  // 生成视频封面
  const getVideoPoster = useMemo(() => {
    if (!src) return undefined;

    const isVid = props.type ? props.type === 'video' : isVideo(src);
    if (!isVid) return undefined;

    // 优先使用 videoPoster
    if (videoPoster) return videoPoster;

    // 其次使用 Video 组件的 poster 属性
    const vProps = props as VideoPropsCombined | CompatibleProps;
    if (vProps.poster) return vProps.poster;

    // 如果开启自动生成，尝试添加视频截帧参数（适用于云存储服务）
    if (autoGeneratePoster) {
      // 阿里云 OSS 视频截帧：?x-oss-process=video/snapshot,t_0,f_jpg
      // 腾讯云 COS 视频截帧：?ci-process=snapshot&time=0
      // 七牛云视频截帧：?vframe/jpg/offset/0
      // 这里以七牛云为例，可根据实际使用的云服务调整
      return `${src}${src.includes('?') ? '&' : '?'}x-oss-process=video/snapshot,t_0,f_jpg`;
    }

    // 最后使用占位图
    return placeholder;
  }, [src, videoPoster, placeholder, autoGeneratePoster, props.type]);

  // 预览资源
  const previewSources: Source[] = useMemo(() => {
    if (!src) return [];

    const isVid = props.type ? props.type === 'video' : isVideo(src);
    return [
      {
        url: src,
        type: isVid ? 'video' : 'image',
        poster: undefined,
      },
    ];
  }, [src, preview, props.type]);

  const renderMedia = () => {
    if (!src) return null;

    const suffix = getSuffixFromUrl(src);
    if (!suffix) return null;

    const isVid = props.type ? props.type === 'video' : isVideo(src);

    if (isVid) {
      const vProps = props as VideoPropsCombined | CompatibleProps;
      return (
        <Video
          className={`${PREFIX_CLS}-video`}
          src={src}
          controls={vProps.controls ?? false}
          poster={getVideoPoster}
          showCenterPlayBtn={vProps.showCenterPlayBtn ?? false}
          showProgress={vProps.showProgress ?? false}
          showPlayBtn={vProps.showPlayBtn ?? false}
          showFullscreenBtn={vProps.showFullscreenBtn}
          showMuteBtn={vProps.showMuteBtn}
          autoplay={vProps.autoplay}
          loop={vProps.loop}
          muted={vProps.muted}
          objectFit={vProps.objectFit ?? 'cover'}
          onLoadedData={() => setLoading(false)}
          onError={() => {
            setLoading(false);
            setError(true);
          }}
        />
      );
    }

    const iProps = props as ImagePropsCombined | CompatibleProps;
    return (
      <Image
        className={`${PREFIX_CLS}-image`}
        src={src}
        mode={iProps.mode ?? 'aspectFill'}
        showMenuByLongpress={iProps.showMenuByLongpress}
        lazyLoad={lazyLoad}
        onLoad={() => setLoading(false)}
        onError={() => {
          setLoading(false);
          setError(true);
        }}
      />
    );
  };

  const showOverlayPlayIcon = () => {
    if (!src) return false;
    const isVid = props.type ? props.type === 'video' : isVideo(src);
    if (!isVid) return false;
    const vProps = props as VideoPropsCombined | CompatibleProps;
    return !!vProps.controls;
  };

  const isVideoContent = useMemo(() => {
    if (!src) return false;
    return props.type ? props.type === 'video' : isVideo(src);
  }, [src, props.type]);

  // 视频加载超时处理（2秒后自动结束 loading 状态）
  useEffect(() => {
    if (!isVideoContent || !loading) return;

    const timer = setTimeout(() => {
      setLoading(false);
    }, 2000);

    return () => clearTimeout(timer);
  }, [isVideoContent, loading]);

  return (
    <View
      className={classnames(PREFIX_CLS, className, {
        [`${PREFIX_CLS}-loading`]: loading && showLoading,
        [`${PREFIX_CLS}-error`]: error,
      })}
      style={{
        ...style,
        width: typeof width === 'number' ? `${width}px` : width,
        height: typeof height === 'number' ? `${height}px` : height,
      }}
      onClick={(e) => {
        if (preview && !error) {
          Taro.previewMedia({ sources: previewSources });
        }
        onClick?.(e);
      }}
    >
      {/* 占位图 */}
      {loading && showLoading && placeholder && (
        <Image
          className={`${PREFIX_CLS}-placeholder`}
          src={placeholder}
          mode="aspectFill"
        />
      )}

      {/* 加载状态 - 图片用骨架屏，视频用占位图 */}
      {loading && showLoading && !placeholder && (
        <>
          {isVideoContent ? (
            <View className={`${PREFIX_CLS}-video-placeholder`}>
              <Icon name="PlayCircle" size={40} color="#999" />
            </View>
          ) : (
            <View className={`${PREFIX_CLS}-skeleton`} />
          )}
        </>
      )}

      {/* 错误状态 */}
      {error && (
        <View className={`${PREFIX_CLS}-error-placeholder`}>
          <Icon name="Picture" size={24} color="#ccc" />
        </View>
      )}

      {/* 实际媒体内容 */}
      {!error && renderMedia()}

      {/* 视频播放图标 */}
      {showOverlayPlayIcon() && !error ? (
        <Icon
          className={`${PREFIX_CLS}-video-icon`}
          name="PlayArrowFilled"
          size={36}
        />
      ) : null}

      {/* 视频标识图标（右下角） */}
      {isVideoContent && !error && (
        <View className={`${PREFIX_CLS}-video-badge`}>▶</View>
      )}
    </View>
  );
};

export default Media;
